#!/usr/bin/env python
import logging
import sys
import os

from pid import PidFile
from pid.base import PidFileAlreadyLockedError

basedir = os.path.dirname(os.path.abspath(__file__))
from pymongo.errors import OperationFailure
# from backup_utils import get_command
from backup_utils import get_all_shards
from backup_utils import get_host_port_by_string
from backup_utils import send_message

from mongo_connect.mongo_get_connect import get_connect
from mongo_connect.mongo_get_connect import mongo_connect_replset

from mongo_connect import get_oplog_to_backup

from oplog_server import OplogGet

from backup_utils import make_dir

log = logging.getLogger(__name__)

formatter = logging.basicConfig(filename="hehe.log",
                                level=logging.DEBUG,
                                format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                                datefmt='%a, %d %b %Y %H:%M:%S')


def increment_backup(backup_config, backup_path, flush_rt):
    """增量备份入口函数"""
    source_instance_list_string = backup_config.get('source_instance_list')
    source_host, source_port = get_host_port_by_string(source_instance_list_string)

    source_mongo_user = backup_config.get('source_mongo_user')
    source_mongo_psw = backup_config.get('source_mongo_psw')
    authentication_database = backup_config.get('authentication_database')
    db_colls = backup_config.get('db_colls')

    mongodb_connect = get_connect(host=source_host, port=source_port, username=source_mongo_user,
                                  password=source_mongo_psw, auth_source=authentication_database)
    is_mongos = mongodb_connect.is_mongos
    if is_mongos is True:
        mongo_shards = get_all_shards(mongodb_connect)
        mongo_shards_list = mongo_shards.get('shards')
        mongodb_connect.close()
        for shard in mongo_shards_list:
            connect_instance_list = shard.get('host').split('/')[1].split(',')
            oplog_replset_get(connect_instance_list=connect_instance_list, source_mongo_user=source_mongo_user,
                              auth_source=authentication_database, password=source_mongo_psw, backup_path=backup_path,
                              flush_rt=flush_rt, db_colls=db_colls)
        # backup_list = get_oplog_to_backup(mongodb_connect=mongodb_connect)
    else:
        mongodb_connect.close()
        connect_instance_list = source_instance_list_string.split(',')
        oplog_replset_get(connect_instance_list=connect_instance_list, source_mongo_user=source_mongo_user,
                          auth_source=authentication_database, password=source_mongo_psw, backup_path=backup_path,
                          flush_rt=flush_rt)


def oplog_replset_get(**kwargs):
    get_oplog_pid = os.fork()
    if get_oplog_pid == 0:
        backup_path = kwargs.get('backup_path')
        write_mod = kwargs.get('write_mod', 'ab')
        connect_instance_list = kwargs.get('connect_instance_list')
        source_mongo_user = kwargs.get('source_mongo_user')
        authentication_database = kwargs.get('auth_source')
        flush_rt = kwargs.get('flush_rt', 0)
        source_mongo_psw = kwargs.get('password')
        db_colls = kwargs.get('db_colls')
        try:
            mongo_repl_set_connect = mongo_connect_replset(connect_instance_list, username=source_mongo_user,
                                                           auth_source=authentication_database,
                                                           password=source_mongo_psw,
                                                           read_preference='secondaryPreferred')
        except Exception as e:
            log.exception("mongodb get replset connect error . ")
            log.exception(str(e))
            message_to_send = "MongoDB({connect_instance_list}) 可能由于鉴权出现问题等原因,连接失败.".format(
                connect_instance_list=connect_instance_list)
            send_message(message_to_send)
            sys.exit(1)
        os.umask(0)
        os.setsid()
        # do something
        try:
            replset_name = mongo_repl_set_connect.admin.command('replSetGetStatus').get('set')
        except OperationFailure as e:
            message_to_send = "MongoDB({connect_instance_list}) 可能由于鉴权出现问题等原因,获取副本集名称失败.".format(
                connect_instance_list=connect_instance_list)
            # log.info(message_to_send)
            send_message(message_to_send)
            log.exception("get replset error ")
            log.exception(str(e))
            sys.exit(1)
        oplog_get_pid_path = '{backup_path}/oplog_increment/{replset_name}/pid'.format(backup_path=backup_path,
                                                                                       replset_name=replset_name)
        make_dir(oplog_get_pid_path)
        try:
            pid_file = "{oplog_get_pid_path}/get_oplog.pid".format(oplog_get_pid_path=oplog_get_pid_path)
            with PidFile(pidname=pid_file):
                oplog_directory = '{backup_path}/oplog_increment/{replset_name}/oplog'.format(backup_path=backup_path,
                                                                                              replset_name=replset_name)
                oplog_get = OplogGet(mongo_connect=mongo_repl_set_connect, oplog_directory=oplog_directory,
                                     write_mod=write_mod, flush_rt=flush_rt, db_colls=db_colls)
                oplog_get.oplog_get(ts_begging_position=1)
                sys.exit(0)
        except PidFileAlreadyLockedError as e:
            log.info("There is already get oplog procedure running , and return here . ")
            sys.exit(0)
    else:
        return
